package com.block.channel.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.block.common.annotate.RedisLock;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.util.BigDecimalUtil;
import com.block.db.entity.ChannelBaseInfo;
import com.block.db.entity.ChannelRegisterResultInfo;
import com.block.db.mapper.ChannelRegisterResultInfoMapper;
import com.block.channel.service.IChannelRegisterResultInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * <p>
 * 渠道注册结果信息 服务实现类
 * </p>
 *
 * @author 
 * @since 2023-10-11
 */
@Service
public class ChannelRegisterResultInfoServiceImpl extends ServiceImpl<ChannelRegisterResultInfoMapper, ChannelRegisterResultInfo> implements IChannelRegisterResultInfoService {

    @Autowired
    NotifyExceptionService notifyExceptionService;

    // 加同步锁
    @Override
    @RedisLock(lockName = "CHANNEL::REGISTER::COUNT::", key = "#channelCode" )
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public ChannelRegisterResultInfo getRegResultInfo(String dateInfo, String channelCode, ChannelBaseInfo channelBaseInfo){

        try {

            ChannelRegisterResultInfo resultInfo = this.baseMapper.getEntityByDateInfoAndCodeLock(dateInfo, channelBaseInfo.getChannelCode());
            if (ObjectUtil.isEmpty(resultInfo)){
                resultInfo = new ChannelRegisterResultInfo();
                resultInfo.setDateInfo(dateInfo);
                resultInfo.setChannelName(channelBaseInfo.getChannelName());
                resultInfo.setChannelCode(channelBaseInfo.getChannelCode());
                resultInfo.setAdminName(channelBaseInfo.getAdminName());
                boolean save = this.save(resultInfo);
                if (!save){
                    throw new RuntimeException("保存注册信息失败");
                }
                // 查询
                resultInfo = this.baseMapper.getEntityByDateInfoAndCodeLock(dateInfo, channelBaseInfo.getChannelCode());
            }

            // 更新注册结算信息
            // 该渠道已经结算的数量
            Integer settleNumber = this.querySettleNumber(channelBaseInfo.getChannelCode(), null);

            Integer todayRegisterNumber = resultInfo.getRegisterNumber() + 1;

            ChannelRegisterResultInfo updateEntity = new ChannelRegisterResultInfo();
            updateEntity.setId(resultInfo.getId());
            updateEntity.setRegisterNumber(todayRegisterNumber);
            if (settleNumber < channelBaseInfo.getNoDiscountNumber()){

                // 不折扣数量还不足，直接结算，不折扣
                updateEntity.setRegisterRealNumber(todayRegisterNumber);
                updateEntity.setRegisterCost(NumberUtil.mul(channelBaseInfo.getPriceAmount(), new BigDecimal(todayRegisterNumber)));
            }else{

                // 查询除了今天，已经结算的数量
                Integer notTodaySettleNumber = this.querySettleNumber(channelBaseInfo.getChannelCode(), dateInfo);

                // 折扣计算注册成本
                // 当天不折扣的注册数量
                Integer  todayNoDiscountNumber =  0;
                if (notTodaySettleNumber < channelBaseInfo.getNoDiscountNumber()){
                    todayNoDiscountNumber = channelBaseInfo.getNoDiscountNumber() - notTodaySettleNumber;
                }

                // 当天需要折扣的数量
                Integer todayRealNumber = todayRegisterNumber - todayNoDiscountNumber;

                // 根据比率计算出，需要折扣数量的实际数量
                BigDecimal todayRealNumberBigdecimal = NumberUtil.mul(new BigDecimal(todayRealNumber), channelBaseInfo.getChannelRate());

                // 折扣的数量 + 不折扣的数量
                todayRealNumberBigdecimal = todayRealNumberBigdecimal.setScale(0, RoundingMode.FLOOR).add(new BigDecimal(todayNoDiscountNumber));

                // 如果结算数量，大于已经结算数量时，才进行结算
                if (todayRealNumberBigdecimal.compareTo(new BigDecimal(resultInfo.getRegisterRealNumber())) > 0){
                    // 只有实际结算数量大于已经结算数量时，才进行更新
                    updateEntity.setRegisterRealNumber(todayRealNumberBigdecimal.intValue());
                    updateEntity.setRegisterCost(NumberUtil.mul(channelBaseInfo.getPriceAmount(), todayRealNumberBigdecimal));
                }
            }

            boolean b = this.updateById(updateEntity);
            if (b){
                return this.baseMapper.getEntityByDateInfoAndCodeLock(dateInfo, channelBaseInfo.getChannelCode());
            }

            return null;
        }catch (Exception exception){
            exception.printStackTrace();
            String message = StrUtil.format("dateInfo:{}; channelCode: {}", dateInfo, channelCode);
            notifyExceptionService.notifyNoticeInfo("REGISTER_COUNT_ERROR", "注册统计异常", message, exception);
        }
        return null;
    }

    /**
     * 查询渠道已经结算的数量
     *
     */
    public Integer querySettleNumber(String channelCode, String dateInfo){
        Integer settleNumber = this.baseMapper.querySettleNumber(channelCode, dateInfo);
        return ObjectUtil.isNotEmpty(settleNumber)?settleNumber:0;
    }

}
